﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using TradePublish.Common;
using Winista.Text.HtmlParser;
using Winista.Text.HtmlParser.Filters;
using Winista.Text.HtmlParser.Util;
using System.Threading;
using System.Text.RegularExpressions;
using Winista.Text.HtmlParser.Tags;
using System.Text;
using log4net;
using System.Reflection;
namespace TradePublish.SysThread.Grasp
{
    /// <summary>
    ///DetectThread  每隔1小时，检查公告是否有最新的公告。
    ///它的作用是，发现有新的公告，就往REGNO_GIF表中插入公告期号。等待其他采集线程进行采集
    /// </summary>
    public class DetectThread
    {
        //商标公告url
        private static String url = "http://sbj.saic.gov.cn/sbgg/";
        private Thread doThread;
        ILog log = null;
        public DetectThread()
        {
            log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        }

        public void start()
        {
            doThread = new Thread(threadWork);
            doThread.IsBackground = true;
            doThread.Start();
        }

        /// <summary>
        /// 监测线程的主函数
        /// </summary>
        private void threadWork()
        {
            while (true)
            {
                //(1)获取全部最新公告
                List<String> issue = getNew12ISSUE();//内部异常自己处理  期号;日期

                //(2)倒着来看看是否已经处理完毕了
                log.Info("开始读取数据库中最大公告期号...");
                RegnoGifManager regnoGifManager = new RegnoGifManager();
                Int32 hasGraspMaxISSUE = regnoGifManager.getMaxISSUE();//内部异常自己处理
                int newC = 0;
                log.Info("同数据库比较，有" + newC + "个新公告需要采集.");
                for (int i = issue.Count - 1; i >= 0; i--)
                {
                    try
                    {
                        int isNo = Convert.ToInt32(issue[i].Split(';')[0]);
                        if (isNo > hasGraspMaxISSUE)
                        {
                            log.Info("有新的公告期" + isNo);
                            String[] pageStaEnd = getPageNo(isNo);//异常抛出
                            DateTime date = new DateTime(Convert.ToInt32(issue[i].Split(';')[1].Split('年')[0]), Convert.ToInt32(issue[i].Split(';')[1].Split('年')[1].Split('月')[0]), Convert.ToInt32(issue[i].Split(';')[1].Split('月')[1].Split('日')[0]));

                            //插入数据库
                            regnoGifManager.insertNewISSUE(isNo, date, pageStaEnd);//内部异常自己处理
                            newC++;
                        }
                    }
                    catch (Exception err)
                    {
                        log.Error("采集新公告8大类的页码，插入数据库。发生异常", err);
                        Thread.Sleep(5000);
                        i++;
                    }
                }
                log.Info("本检测线程DetectThread休息1小时.");
                Thread.Sleep(3600000);//休息1小时。  
            }
        }


        /// <summary>
        /// 获得最新的公告，列表为当前的最新12期公告，中间出异常，自己解决。
        /// </summary>
        /// <returns></returns>  期号;日期
        private List<String> getNew12ISSUE()
        {
            while (true)
            {
                try
                {
                    log.Info("开始采集最新商标公告..");
                    List<String> issue = new List<String>();
                    GetData gd = new GetData();
                    String html =gd.GetResponse("http://sbj.saic.gov.cn/sbgg/", null);
                    log.Debug("获得公告页面html");

                    #region 分析html
                    Parser parser = Parser.CreateParser(html, "UTF-8"); ;
                    NodeFilter filter = new HasAttributeFilter("class", "titlemes");
                    NodeList nodes = parser.ExtractAllNodesThatMatch(filter);
                    List<String> urls = new List<String>();
                    if (nodes != null)
                    {
                        for (int i = 0; i < nodes.Size(); i++)
                        {
                            INode node = nodes.ElementAt(i);
                            Parser parserT = Parser.CreateParser(node.ToHtml(), "UTF-8"); ;
                            NodeFilter filterT = new NodeClassFilter(typeof(Winista.Text.HtmlParser.Tags.ATag));
                            NodeList nodesT = parserT.ExtractAllNodesThatMatch(filterT);
                            if (nodesT != null)
                            {
                                for (int j = 0; j < nodesT.Size(); j++)
                                {
                                    Winista.Text.HtmlParser.Tags.ATag tag = (Winista.Text.HtmlParser.Tags.ATag)(nodesT.ElementAt(j) is ITag ? nodesT.ElementAt(j) as ITag : null);
                                    if (tag != null && !tag.IsEndTag())
                                    {
                                        String txt = tag.LinkText;
                                        if (txt != null)
                                        {
                                            String no = "";
                                            String date = "";
                                            MatchCollection mc = Regex.Matches(txt, @"第\d+期", RegexOptions.IgnoreCase);
                                            foreach (Match mt in mc)
                                            {
                                                no = mt.Value.Substring(1, mt.Value.Length - 2);
                                                break;
                                            }

                                            mc = Regex.Matches(txt, @"初步审定公告日期:[\s\S]*&nbsp;异议", RegexOptions.IgnoreCase);
                                            foreach (Match mt in mc)
                                            {
                                                date = mt.Value.Substring(9, mt.Value.Length - 17);
                                                break;
                                            }
                                            if (!no.Equals("") && !date.Equals(""))
                                            {
                                                issue.Add(no + ";" + date);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    #endregion

                    log.Info("本次从商标局网站采集到" + issue.Count + "个公告。");
                    return issue;
                }
                catch (Exception ee)
                {
                    log.Error("异常：", ee);
                    Thread.Sleep(30000);//发生异常，暂停30秒
                }
            }
        }

        /// <summary>
        /// 根据公告期号，获得该公告期8类数据的开始、结束页码，注意是gif页码的
        /// </summary>
        /// <param name="issue"></param>
        /// <returns></returns>
        /// 0- 商标初步审定公告 
        /// 1- 商标注册公告 
        /// 2-商标转让公告 
        /// 3-变更许可人/被许可人名义公告 （不是每期都存在） 
        /// 4-商标注册证无效公告 （不是每期都存在）
        /// 5-注册商标注销公告 （不是每期都存在）
        /// 6-商标异议公告 （不是每期都存在）
        /// 7-未续展商标注销公告（不是每期都存在） 
        private String[] getPageNo(int issue)
        {
            String[] rtn = new String[8];
            String html = GetData.GetResponse("http://saicsearch.saic.gov.cn/gszj/sbgg/show.jsp?iszk=2&qh=" + issue, null, Encoding.GetEncoding("GBK"));

            Parser parser = Parser.CreateParser(html, "GBK"); ;
            NodeFilter filter = new NodeClassFilter(typeof(TableTag));
            NodeList nodes = parser.ExtractAllNodesThatMatch(filter);
            if (nodes != null)
            {
                TableTag tag = (TableTag)(nodes.ElementAt(0) is ITag ? nodes.ElementAt(0) as ITag : null);
                if (tag != null && !tag.IsEndTag())
                {
                    Parser parserT = Parser.CreateParser(tag.ToHtml(), "GBK"); ;
                    NodeFilter filterT = new NodeClassFilter(typeof(Winista.Text.HtmlParser.Tags.ATag));
                    NodeList nodesT = parserT.ExtractAllNodesThatMatch(filterT);
                    if (nodesT != null)
                    {
                        int lastIndex = -1;//上次的索引号，为了取得结束页码
                        for (int j = 0; j < nodesT.Size(); j++)
                        {
                            Winista.Text.HtmlParser.Tags.ATag tagT = (Winista.Text.HtmlParser.Tags.ATag)(nodesT.ElementAt(j) is ITag ? nodesT.ElementAt(j) as ITag : null);
                            if (tagT != null && !tagT.IsEndTag())
                            {
                                String href = tagT.GetAttribute("href");
                                String txt = tagT.LinkText;
                                if (txt != null)
                                {
                                    int start = -1;
                                    MatchCollection mc = Regex.Matches(href, @"yhq=\d+&", RegexOptions.IgnoreCase);
                                    foreach (Match mt in mc)
                                    {
                                        start = Convert.ToInt16(mt.Value.Substring(4, mt.Value.Length - 5));
                                        break;
                                    }
                                    if (start < 0)
                                    {
                                        continue;
                                    }
                                    if (lastIndex >= 0)
                                    {
                                        rtn[lastIndex] = rtn[lastIndex] + "-" + (start - 1);
                                    }
                                    if (txt.IndexOf("商标初步审定公告") == 0)
                                    {
                                        rtn[0] = "" + start;
                                        lastIndex = 0;
                                    }
                                    else if (txt.IndexOf("商标注册公告") == 0)
                                    {
                                        rtn[1] = "" + start;
                                        lastIndex = 1;
                                    }
                                    else if (txt.IndexOf("商标转让公告") == 0)
                                    {
                                        rtn[2] = "" + start;
                                        lastIndex = 2;
                                    }
                                    else if (txt.IndexOf("变更许可人/被许可人名义公告") == 0)
                                    {
                                        rtn[3] = "" + start;
                                        lastIndex = 3;
                                    }
                                    else if (txt.IndexOf("商标注册证无效公告") == 0)
                                    {
                                        rtn[4] = "" + start;
                                        lastIndex = 4;
                                    }
                                    else if (txt.IndexOf("注册商标注销公告") == 0)
                                    {
                                        rtn[5] = "" + start;
                                        lastIndex = 5;
                                    }
                                    else if (txt.IndexOf("商标异议公告") == 0)
                                    {
                                        rtn[6] = "" + start;
                                        lastIndex = 6;
                                    }
                                    else if (txt.IndexOf("未续展商标注销公告") >= 0)
                                    {
                                        rtn[7] = "" + start;
                                        lastIndex = 7;
                                    }
                                    else
                                    {
                                        lastIndex = -1;
                                    }
                                }
                            }
                        }
                    }
                }

            }
            return rtn;

        }
    }

}